﻿using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml;
using System.Xml.Linq;
#nullable enable

namespace Xman.Extensions.Core
{
    public static class XmlExtensions
    {
        /// <summary>
        /// xml字符串转为XmlDocument
        /// </summary>
        /// <param name="xmlstring"></param>
        /// <returns></returns>
        public static XmlDocument CreateDocument(this string xml)
        {
            XmlDocument doc = new();
            var reader = new XmlTextReader(new StringReader(xml));
            XmlReaderSettings settings = new() { IgnoreComments = true };
            XmlReader xmlreader = XmlReader.Create(reader, settings);
            doc.Load(xmlreader);
            return doc;
        }

        /// <summary>
        /// XElement 去除命名空间
        /// </summary>
        /// <param name="element"></param>
        /// <returns></returns>
        public static XElement? WithoutNamespaces(this XElement element)
        {
            if (element == null) return null;
            return new XElement(element.Name.LocalName,element.Nodes().Select(GetChildNode), GetAttributes(element));
        }

        /// <summary>
        /// xml字符串转为XElement
        /// </summary>
        /// <param name="xml"></param>
        /// <returns></returns>
        public static XElement ToXElement(this string xml)
        {
            return XElement.Parse(xml);
        }

        /// <summary>
        /// 获取XAttribute 的值
        /// </summary>
        /// <param name="attribute"></param>
        /// <param name="defaultvalue"></param>
        /// <returns></returns>
        public static string GetAttributeValue(this XAttribute attribute, string defaultvalue = "")
        {
            return attribute == null ? defaultvalue : attribute.Value;
        }

        /// <summary>
        ///  获取XAttribute 的值
        /// </summary>
        /// <param name="element"></param>
        /// <param name="attributename"></param>
        /// <param name="defaultvalue"></param>
        /// <returns></returns>
        public static string? GetAttributeValue(this XElement? element,string attributename="value",string defaultvalue = "")
        {
            return element?.Attribute(attributename) == null ? defaultvalue : element.Attribute(attributename)?.Value;
        }

        /// <summary>
        /// Gets the first (in document order) child element with the specified System.Xml.Linq.XName.
        /// </summary>
        /// <param name="element"></param>
        /// <param name="path"></param>
        /// <param name="splitstr"></param>
        /// <returns></returns>
        public static XElement? ElementPath(this XElement? element,string path,string splitstr="/")
        {
            foreach (var p in path.Split(splitstr))
            {
                if (element == null)
                {
                    return element;
                }
                element = element?.Element(p);
            }
            return element;
        }

        private static IEnumerable<XAttribute> GetAttributes(XElement e) => (e.HasAttributes) ? e.Attributes().Where(a => !a.IsNamespaceDeclaration).Select(a => new XAttribute(a.Name.LocalName, a.Value)) : Enumerable.Empty<XAttribute>();

        private static XNode? GetChildNode(XNode e) => (e.NodeType == XmlNodeType.Element) ? (e as XElement)?.WithoutNamespaces() : e;

    }
}
